﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Linq;
using System.Reflection;
using System.Windows.Forms;
using Autodesk.Revit.ApplicationServices;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI;
using YArchitech.Revit;

namespace Assist
{
	public class AssistFunc
	{
        public static ModelCurve CreateNewCurve(Autodesk.Revit.ApplicationServices.Application app, Document doc, Curve curve)
		{
			XYZ origin = new XYZ(0.0, 0.0, 0.0);
			Plane plane = RevitVersionFuncs.CreatePlanByNormalAndOrigin(new XYZ(0.0, 0.0, 1.0), origin);
			SketchPlane sketchPlane = doc.CreatYJKSketchPlane(plane);
			return doc.Create.NewModelCurve(curve, sketchPlane);
		}

        public static ModelLine CreateNewLine(Autodesk.Revit.ApplicationServices.Application app, Document doc, XYZ ptstart, XYZ ptend)
		{
			Line curve = app.CreatYJKLine(ptstart, ptend, true);
			return AssistFunc.CreateNewCurve(app, doc, curve) as ModelLine;
		}

        public static ModelArc CreateNewArc(Autodesk.Revit.ApplicationServices.Application app, Document doc, XYZ ptstart, XYZ ptend, XYZ pton)
		{
			Arc curve = app.CreatYJKArc(ptstart, ptend, pton);
			return AssistFunc.CreateNewCurve(app, doc, curve) as ModelArc;
		}

        public static void CreateNewArc(Autodesk.Revit.ApplicationServices.Application app, Document doc, XYZ ptcenter, double radius, double startang, double endang)
		{
			Arc curve = doc.CreatYJKArc(ptcenter, radius, startang, endang, XYZ.BasisX, XYZ.BasisY);
			AssistFunc.CreateNewCurve(app, doc, curve);
		}

		public static void RandomPts(List<XYZ> arpts)
		{
			if (arpts.Count <= 0)
			{
				return;
			}
			for (int i = 0; i < 2; i++)
			{
				XYZ item = arpts.First<XYZ>();
				arpts.RemoveAt(0);
				arpts.Add(item);
			}
		}

		public static double mmToFeet(double val)
		{
			return val / 304.8;
		}

		public static double feetToMM(double val)
		{
			return val * 304.8;
		}

		public static double feet2ToM2(double val)
		{
			return val / 10.76391041671;
		}

		public static double m2ToFeet2(double val)
		{
			return val * 10.76391041671;
		}

		public static double AngleToRadian(double val)
		{
			return val * Math.PI / 180.0;
		}

		public static double RadianToAngle(double val)
		{
			return val * 180.0 / Math.PI;
		}

		public static void InitRadian(ref double val)
		{
			while (val > Math.PI*2)
			{
				val -= Math.PI*2;
			}
			while (val < Math.PI*2)
			{
				val += Math.PI*2;
			}
		}

		public static bool IsOdd(int nSource)
		{
			return nSource / 2 * 2 != nSource;
		}

		public static string GetAppRootPath()
		{
            return @"C:\Hongye\HYRME2018";

			string location = Assembly.GetExecutingAssembly().Location;
			int length = location.LastIndexOf("\\");
			string text = location.Substring(0, length);
			length = text.LastIndexOf("\\");
			return text.Substring(0, length);
		}

		public static ViewType GetCurrentViewType(Document doc)
		{
			return doc.ActiveView.ViewType;
		}

		public static Level GetCurrentViewLevel(Document doc)
		{
			return doc.ActiveView.GenLevel;
		}

		public static Phase GetCurrentViewPhase(Document doc)
		{
			ElementId id = doc.ActiveView.get_Parameter(BuiltInParameter.VIEW_PHASE).AsElementId();
			return RevitVersionFuncs.GetElement(doc, id) as Phase;
		}

		public static List<Level> GetAllLevel(Document doc)
		{
			return (from l in new FilteredElementCollector(doc).OfClass(typeof(Level)).OfCategory(BuiltInCategory.OST_Levels)
			orderby ((Level)l).Elevation
			select l).Cast<Level>().ToList<Level>();
		}

		public static List<Level> GetAllLevel(Document doc, Level minLevel, Level maxLevel)
		{
			FilteredElementCollector filteredElementCollector = new FilteredElementCollector(doc);
			new List<Level>();
			List<Level> list = new List<Level>();
			if (minLevel == null && maxLevel == null)
			{
				list = (from l in filteredElementCollector.OfClass(typeof(Level)).OfCategory(BuiltInCategory.OST_Levels)
				orderby ((Level)l).Elevation
				select l).Cast<Level>().ToList<Level>();
			}
			else
			{
				if (minLevel == null && maxLevel != null)
				{
					using (List<Level>.Enumerator enumerator = (from l in filteredElementCollector.OfClass(typeof(Level)).OfCategory(BuiltInCategory.OST_Levels)
					orderby ((Level)l).Elevation
					select l).Cast<Level>().ToList<Level>().GetEnumerator())
					{
						while (enumerator.MoveNext())
						{
							Level level = enumerator.Current;
							if (level.Elevation <= maxLevel.Elevation)
							{
								list.Add(level);
							}
						}
						return list;
					}
				}
				if (minLevel != null && maxLevel == null)
				{
					using (List<Level>.Enumerator enumerator = (from l in filteredElementCollector.OfClass(typeof(Level)).OfCategory(BuiltInCategory.OST_Levels)
					orderby ((Level)l).Elevation
					select l).Cast<Level>().ToList<Level>().GetEnumerator())
					{
						while (enumerator.MoveNext())
						{
							Level level2 = enumerator.Current;
							if (level2.Elevation >= minLevel.Elevation)
							{
								list.Add(level2);
							}
						}
						return list;
					}
				}
				if (minLevel != null && maxLevel != null)
				{
					foreach (Level level3 in (from l in filteredElementCollector.OfClass(typeof(Level)).OfCategory(BuiltInCategory.OST_Levels)
					orderby ((Level)l).Elevation
					select l).Cast<Level>().ToList<Level>())
					{
						if (level3.Elevation >= minLevel.Elevation && level3.Elevation <= maxLevel.Elevation)
						{
							list.Add(level3);
						}
					}
				}
			}
			return list;
		}

		public static Level GetLevelByName(Document doc, string name)
		{
			ElementCategoryFilter elementCategoryFilter = new ElementCategoryFilter(BuiltInCategory.OST_Levels);
			IEnumerable<Element> enumerable = new FilteredElementCollector(doc).OfClass(typeof(Level)).WherePasses(elementCategoryFilter).ToElements();
			Level result = null;
			foreach (Element element in enumerable)
			{
				Level level = element as Level;
				if (level.Name.ToString().Equals(name))
				{
					result = level;
				}
			}
			return result;
		}

		public static GridType GetGridTypeByName(Document doc, string name)
		{
			GridType result = null;
			FilteredElementCollector filteredElementCollector = new FilteredElementCollector(doc);
			filteredElementCollector.OfClass(typeof(GridType));
			foreach (Element element in filteredElementCollector)
			{
				GridType gridType = (GridType)element;
				if (gridType.Name.ToString().Equals(name))
				{
					result = gridType;
				}
			}
			return result;
		}

		public static WallType GetWallTypeByName(Document doc, string name)
		{
			WallType result = null;
			FilteredElementCollector filteredElementCollector = new FilteredElementCollector(doc);
			filteredElementCollector.OfClass(typeof(WallType));
			foreach (Element element in filteredElementCollector)
			{
				WallType wallType = (WallType)element;
				if (wallType.Name.ToString().Equals(name))
				{
					result = wallType;
				}
			}
			return result;
		}

		public static DimensionType GetDimTypeByName(Document doc, string name, DimensionStyleType styleType)
		{
			DimensionType result = null;
			FilteredElementCollector filteredElementCollector = new FilteredElementCollector(doc);
			filteredElementCollector.OfClass(typeof(DimensionType));
			foreach (Element element in filteredElementCollector)
			{
				DimensionType dimensionType = (DimensionType)element;
				if (dimensionType.Name.ToString().CompareTo(name) == 0 && dimensionType.StyleType == styleType)
				{
					result = dimensionType;
					break;
				}
			}
			return result;
		}

		public static int CompressArray(List<XYZ> arPt)
		{
			List<XYZ> list = new List<XYZ>();
			foreach (XYZ xyz in arPt)
			{
				bool flag = false;
				foreach (XYZ pt in list)
				{
					if (GeoUtil.IsPointEqual(xyz, pt))
					{
						flag = true;
					}
				}
				if (!flag)
				{
					list.Add(xyz);
				}
			}
			arPt.Clear();
			foreach (XYZ item in list)
			{
				arPt.Add(item);
			}
			return arPt.Count;
		}

		public static int CompressArray(List<Element> arElements)
		{
			List<Element> list = new List<Element>();
			foreach (Element item in arElements)
			{
				if (!list.Contains(item))
				{
					list.Add(item);
				}
			}
			arElements.Clear();
			foreach (Element item2 in list)
			{
				arElements.Add(item2);
			}
			return arElements.Count;
		}

		public static int CompressArray(List<Grid> arObj)
		{
			List<Grid> list = new List<Grid>();
			foreach (Grid item in arObj)
			{
				if (!list.Contains(item))
				{
					list.Add(item);
				}
			}
			arObj.Clear();
			foreach (Grid item2 in list)
			{
				arObj.Add(item2);
			}
			return arObj.Count;
		}

		public static Bitmap ResizeImage(Bitmap bmp, int newW, int newH)
		{
			Bitmap result;
			try
			{
				Bitmap bitmap = new Bitmap(newW, newH);
				Graphics graphics = Graphics.FromImage(bitmap);
				graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
                graphics.DrawImage(bmp, new System.Drawing.Rectangle(0, 0, newW, newH), new System.Drawing.Rectangle(0, 0, bmp.Width, bmp.Height), GraphicsUnit.Pixel);
				graphics.Dispose();
				result = bitmap;
			}
			catch
			{
				result = null;
			}
			return result;
		}

		public static bool SetDoorWinWidth(FamilyInstance obj, double dWidth)
		{
			if (obj.Category.Id.IntegerValue == -2000014)
			{
				obj.get_Parameter(BuiltInParameter.CASEWORK_WIDTH).Set(AssistFunc.mmToFeet(dWidth));
				return true;
			}
			if (obj.Category.Id.IntegerValue == -2000023)
			{
				Parameter parameter = obj.get_Parameter(BuiltInParameter.CASEWORK_WIDTH);
				parameter.AsDouble();
				AssistFunc.feetToMM(parameter.AsDouble()).ToString();
				parameter.Set(AssistFunc.mmToFeet(dWidth));
				AssistFunc.feetToMM(parameter.AsDouble()).ToString();
				return true;
			}
			return false;
		}

		public static string ParameterToString(Document doc, Parameter param)
		{
			string result = "";
			if (param == null)
			{
				return result;
			}
			switch ((int)param.StorageType)
			{
			case 1:
				result = param.AsInteger().ToString();
				break;
			case 2:
				result = AssistFunc.feetToMM(param.AsDouble()).ToString();
				break;
			case 3:
				result = param.AsString();
				break;
			case 4:
			{
				ElementId id = param.AsElementId();
				result = RevitVersionFuncs.GetElement(doc, id).Name;
				break;
			}
			}
			return result;
		}

		public static bool LoadStandardFamily(UIApplication uiApp)
		{
			uiApp.Application.GetLibraryPaths();
			string text;
			uiApp.Application.GetLibraryPaths().TryGetValue("Metric Library", out text);
			if (string.IsNullOrEmpty(text))
			{
				text = "c:\\";
			}
			OpenFileDialog openFileDialog = new OpenFileDialog();
			openFileDialog.InitialDirectory = text;
			openFileDialog.Filter = "Family Files (*.rfa)|*.rfa";
			if (DialogResult.OK == openFileDialog.ShowDialog())
			{
				Family family = null;
				return uiApp.ActiveUIDocument.Document.LoadFamily(openFileDialog.FileName, out family);
			}
			return false;
		}

		public static ICollection<ElementId> GetAllFamilyInstance(Document doc, BuiltInCategory builtInCategory)
		{
			return new FilteredElementCollector(doc).OfClass(typeof(FamilyInstance)).OfCategory(builtInCategory).ToElementIds();
		}

		public static List<string> GetSystemElementList<T>(Document doc)
		{
			List<string> list = new List<string>();
			try
			{
				foreach (Element element in new FilteredElementCollector(doc).OfClass(typeof(T)).ToElements())
				{
					if (element is T)
					{
						list.Add(element.Name);
					}
				}
			}
			catch (Exception ex)
			{
				ex.Message.ToString();
			}
			return list;
		}

		public static List<TextNoteType> GetSystemFontTypeArray(Document doc)
		{
			List<TextNoteType> list = new List<TextNoteType>();
			try
			{
				foreach (Element element in new FilteredElementCollector(doc).OfClass(typeof(TextNoteType)).ToElements())
				{
					TextNoteType textNoteType = element as TextNoteType;
					if (textNoteType != null && !textNoteType.Name.Contains("HY_Leader_"))
					{
						list.Add(textNoteType);
					}
				}
			}
			catch (Exception ex)
			{
				ex.Message.ToString();
			}
			return list;
		}

		public static List<string> GetSystemFontTypeStringArray(Document doc)
		{
			List<string> list = new List<string>();
			foreach (TextNoteType textNoteType in AssistFunc.GetSystemFontTypeArray(doc))
			{
				if (!(textNoteType.Name == "LZ_TXT_0.0001"))
				{
					list.Add(textNoteType.Name);
				}
			}
			return list;
		}

		public static List<ElementId> SubCollection(List<ElementId> a, List<ElementId> b)
		{
			List<ElementId> list = new List<ElementId>();
			foreach (ElementId item in a)
			{
				if (!b.Contains(item))
				{
					list.Add(item);
				}
			}
			return list;
		}

		public static double precision = 1E-06;
	}
}
